package edu.mit.simile.longwell;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import jena.rdfparse;


import org.apache.log4j.Logger;


import com.hp.hpl.jena.rdf.model.Model;

public class Utilities {

    final static public String s_bnodePrefix = "urn:bnode:";

    final static protected Logger s_logger = Logger.getLogger(Utilities.class);




    
    static public double parseDouble(String s, double def) {
        try {
            return Double.parseDouble(s);
        } catch (Exception e) {
            return def;
        }
    }
    
    static public long parseLong(String s, long def) {
        try {
            return Long.parseLong(s);
        } catch (Exception e) {
            return def;
        }
    }

    static public String fileToModelLang(File file) {
        return filenameToLang(file.getName());
    }

    static public String urlToModelLang(URL url, String contentType) {
        return urlToModelLang(url.getPath(), contentType);
    }

    static public String urlToModelLang(String url, String contentType) {
        String lang = null;

        if (contentType != null) {
            lang = contentTypeToLang(contentType);
        }
        if (lang == null) {
            lang = filenameToLang(url);
        }

        if (s_logger.isDebugEnabled()) s_logger.debug(url + " -> " + lang);
        return lang;
    }

    static public String contentTypeToLang(String contentType) {
        String lang = null;
        if ("application/rss+xml".equals(contentType) || "application/atom+xml".equals(contentType)) {
            lang = "RSS";
        } else if ("application/rdf+xml".equals(contentType) || "text/xml".equals(contentType)) {
            lang = "RDFXML";
        } else if ("application/n3".equals(contentType) || "text/rdf+n3".equals(contentType)
                || "application/turtle".equals(contentType) || "application/x-turtle".equals(contentType)) {
            lang = "N3";
        }
        if (s_logger.isDebugEnabled()) s_logger.debug(contentType + " -> " + lang);
        return lang;
    }

    static public String filenameToLang(String filename) {
        String contentType = URLConnection.guessContentTypeFromName(filename);
        String lang = null;

        if (contentType != null) {
            lang = contentTypeToLang(contentType);
        }

        if (lang == null) {
            if (filename.endsWith(".gz")) {
                filename = filename.substring(0, filename.length() - ".gz".length());
            }
            if (filename.endsWith(".n3")) {
                lang = "N3";
            } else if (filename.endsWith(".turtle")) {
                lang = "TURTLE";
            } else if (filename.endsWith(".ntriples")) {
                lang = "NTRIPLES";
            } else if (filename.endsWith(".rss")) {
                lang = "RSS";
            } else if (filename.endsWith(".rdf") 
                    || filename.endsWith(".rdfs") 
                    || filename.endsWith(".xml")
                    || filename.endsWith(".owl")) {
                lang = "RDFXML";
            }
        }

        return lang;
    }



    static public String uriToFilename(String uri) {
        return uri.replace(':', '_').replace('/', '_');
    }

 

    static public InputStream getStreamForFile(File file) throws Exception {
        InputStream stream = new FileInputStream(file);
        String name = file.getName();
        if (name.endsWith(".gz")) {
            stream = new GZIPInputStream(stream);
        }
        return stream;
    }
    






    static public void setRequestHeaders(URLConnection conn, String ua) {
        conn.setRequestProperty("User-Agent", ua);
        conn.setRequestProperty("Accept", "application/rdf+xml, text/rdf+n3");
    }

 

    static public File uriToFile(String uri) throws URISyntaxException {
        int percentU = uri.indexOf("%u");
        if (percentU >= 0) {
            StringBuffer sb = new StringBuffer(uri.length());

            int start = 0;
            while (percentU > 0) {
                sb.append(uri.substring(start, percentU));

                char c = (char) Integer.parseInt(uri.substring(percentU + 2, percentU + 6), 16);

                sb.append(c);

                start = percentU + 6;
                percentU = uri.indexOf("%u", start);
            }

            sb.append(uri.substring(start));
            uri = sb.toString();
        }
        return new File(new java.net.URI(uri));
    }

    static public void deleteDirectory(File dir) {
        if (dir.exists()) {
            deleteDirectoryContent(dir);
            dir.delete();
        }
    }

    static public void deleteDirectoryContent(File dir) {
        File[] files = dir.listFiles();
        if (dir.isDirectory() && files != null) {
            for (int i = 0; i < files.length; i++) {
                File file = files[i];
                if (file.isDirectory()) {
                    deleteDirectory(file);
                } else {
                    file.delete();
                }
            }
        }
    }



    static public Coordinates parseCoordinates(String s) {
            if (null == s) return null;
            String[] coords = s.split(",");
            if (coords.length != 2) {
                return null;
            }
            double lat, lng;
            try {
                lat = Double.parseDouble(coords[0]);
                lng = Double.parseDouble(coords[1]);
            } catch (Exception e) {
                return null;
            }
            Coordinates c = new Coordinates(lat, lng);
            return c;
    }
    
    static public Date parseDate(String s) {
        Date d = null;
        
        if (s != null) {
        
            int length = s.length();
    
            if (length == 25 || (length == 20 && s.charAt(19) == 'Z')) {
    
                char c = s.charAt(length - 1);
                int endOfTime;
        
                if (c == 'Z' || c == 'z') {
                    endOfTime = length - 1;
                } else {
                    endOfTime = 19;
                }
        
                try {
                    d = new SimpleDateFormat("yyyy-MM-dd'T'H:m:s").parse(s.substring(0, endOfTime));
                } catch (ParseException e) {
                    return null;
                }
        
                if (endOfTime < length - 1) {
                    int sign = s.charAt(endOfTime) == '+' ? -1 : 1;
                    int hour = Integer.parseInt(s.substring(endOfTime + 1, endOfTime + 3));
                    int minute = Integer.parseInt(s.substring(endOfTime + 4));
        
                    d = new Date(d.getTime() + sign * (hour * 60 + minute) * 60000);
                }
            } else if (length == 10) {
                try {
                    d = new SimpleDateFormat("yyyy-MM-dd").parse(s);
                } catch (ParseException e) {
                    return null;
                }
            }
        }

        return d;
    }

    static public String unparseDate(Date d) {
        // return d != null ? XSDDatatype.XSDdateTime.unparse(d) : null;

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
        String s = sdf.format(d);
        int l = s.length() - 2;

        return s.substring(0, l) + ":" + s.substring(l);
    }

    static public String reformatDate(String s) {
        Date d = parseDate(s);
        if (d != null) {
            return formatDate(d);
        }
        return s;
    }

    static public String formatDate(Date d) {
        return d == null ? null : DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(d);
    }

    static public String abbreviateURI(String uri) {
        int index = uri.lastIndexOf('#') + 1;
        if (index < 1) {
            index = uri.lastIndexOf('/') + 1;
        }
        if (index == uri.length()) {
            return uri;
        }
        return uri.substring(index);
    }

    /**
     * Given a string, convert all instances of [toEscape] to the
     * sequence [escaping][escaped]. Also convert instances of
     * [escaping] to [escaping][escaping].
     *
     * Thus
     *   escape("ten $ = a sawbuck", '$', '=', 'd')
     * returns 
     *   "ten =d == a sawbuck".
     */
    static public String escape(String s, char toEscape, char escaping, char escaped) {
        StringBuffer sb = new StringBuffer();
        char[] chars = s.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];
            if (c == escaping) {
                sb.append(c).append(c);
            } else if (c == toEscape) {
                sb.append(escaping).append(escaped);
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * Inverse of escape().
     */
    static public String unescape(String s, char toEscape, char escaping, char escaped) {
        StringBuffer sb = new StringBuffer();
        char[] chars = s.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];
            if (c == escaping && i < chars.length + 1) {
                char c2 = chars[i + 1];
                if (c2 == escaping) {
                    sb.append(escaping);
                    i++;
                } else if (c2 == escaped) {
                    sb.append(toEscape);
                    i++;
                } else {
                    sb.append(c);
                }
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    private static final String URL_ENCODING = "UTF-8";
}
